﻿using Microsoft.Extensions.Logging;
using NICWebApi.Extensions.DynamicAPI.Options;
using System.Collections.Concurrent;

/// <summary>
/// DynamicAPI操作的工具类
/// </summary>
internal static class Utils
{
    #region 原始实现 - 静态构造函数
    // 不足：在静态构造函数中执行耗时操作，影响启动性能
    // static Utils()
    // {
    //     ActionGroups = GetActionGroups();
    // }
    #endregion

    // 使用延迟初始化提高启动性能
    private static readonly Lazy<IEnumerable<string>> _actionGroups = new Lazy<IEnumerable<string>>(() => GetActionGroups());

    /// <summary>
    /// 默认分组名称
    /// </summary>
    internal const string DefaultGroupName = "Default";

    /// <summary>
    /// 分组名称（使用延迟加载）
    /// </summary>
    internal static IEnumerable<string> ActionGroups => _actionGroups.Value;

    /// <summary>
    /// 配置节名称
    /// </summary>
    internal const string OptionSection = "DynamicApi";

    #region 原始实现 - ActionDict
    // 不足：公开的静态字典没有线程安全保护，可能导致并发问题
    // public static Dictionary<MethodInfo, ActionMeta> ActionDict = new Dictionary<MethodInfo, ActionMeta>();
    #endregion

    // 使用线程安全的集合存储Action元数据
    private static readonly ConcurrentDictionary<MethodInfo, ActionMeta> _actionDict = new ConcurrentDictionary<MethodInfo, ActionMeta>();

    /// <summary>
    /// Action元数据线程安全字典，由ControllerModelConvention收集，key为Controller+Action唯一标识
    /// </summary>
    internal static ConcurrentDictionary<MethodInfo, ActionMeta> ActionDict => _actionDict;

    /// <summary>
    /// 获取所有Action的元数据（返回只读列表）
    /// </summary>
    /// <returns>Action元数据列表</returns>
    public static IReadOnlyList<ActionMeta> GetAllActionMetas() => ActionDict.Values.ToList().AsReadOnly();

    #region 原始实现 - 文件操作
    // 不足：没有缓存机制，每次调用都会重新扫描文件系统
    // public static string[] GetXmlFiles()
    // {
    //     var matcher = new Matcher();
    //     matcher.AddInclude("**/*.xml");
    //     var xmlFiles = matcher.GetResultsInFullPath(AppContext.BaseDirectory).ToArray();
    //     return xmlFiles;
    // }
    //
    // public static string[] GetJsonFiles()
    // {
    //     var matcher = new Matcher();
    //     matcher.AddInclude("**/*.json");
    //     var jsonFiles = matcher.GetResultsInFullPath(AppContext.BaseDirectory).ToArray();
    //     return jsonFiles;
    // }
    #endregion

    // 使用缓存避免重复的文件系统操作
    private static readonly Lazy<string[]> _xmlFilesCache = new Lazy<string[]>(() => FindFiles("**/*.xml"));
    private static readonly Lazy<string[]> _jsonFilesCache = new Lazy<string[]>(() => FindFiles("**/*.json"));

    /// <summary>
    /// 获取当前目录下所有xml文件（带缓存）
    /// </summary>
    /// <returns>XML文件路径数组</returns>
    public static string[] GetXmlFiles() => _xmlFilesCache.Value;

    /// <summary>
    /// 获取当前目录下所有Json文件（带缓存）
    /// </summary>
    /// <returns>JSON文件路径数组</returns>
    public static string[] GetJsonFiles() => _jsonFilesCache.Value;

    /// <summary>
    /// 查找匹配指定模式的文件（带错误处理）
    /// </summary>
    /// <param name="pattern">文件匹配模式</param>
    /// <returns>匹配的文件路径数组</returns>
    private static string[] FindFiles(string pattern)
    {
        try
        {
            var matcher = new Matcher();
            matcher.AddInclude(pattern);
            return matcher.GetResultsInFullPath(AppContext.BaseDirectory).ToArray();
        }
        catch (Exception ex)
        {
            // 记录错误信息
            // 在实际实现中，应该注入ILogger或使用日志抽象
            Console.WriteLine($"查找文件时出错，模式：{pattern}，错误：{ex.Message}");
            return Array.Empty<string>();
        }
    }

    #region 原始实现 - GetOptions
    // 不足：空异常捕获，没有记录错误信息；没有缓存机制
    // public static DynamicApiOptions GetOptions()
    // {
    //     var jsonFiles = GetJsonFiles();
    //     DynamicApiOptions options = default;
    //
    //     foreach (var jsonFile in jsonFiles)
    //     {
    //         try
    //         {
    //             var configuration = new ConfigurationBuilder()
    //                 .AddJsonFile(jsonFile, optional: false, reloadOnChange: true)
    //                 .Build();
    //
    //             options = configuration.GetSection(OptionSection).Get<DynamicApiOptions>();
    //             if (options != null)
    //             {
    //                 break;
    //             }
    //         }
    //         catch
    //         {
    //             // 忽略读取失败的文件
    //             continue;
    //         }
    //     }
    //
    //     // 如果没有找到配置，返回默认配置
    //     return options ?? new DynamicApiOptions();
    // }
    #endregion

    // 使用缓存避免重复读取和解析配置文件
    private static readonly Lazy<DynamicApiOptions> _optionsCache = new Lazy<DynamicApiOptions>(LoadOptions);

    /// <summary>
    /// 获取配置选项（带缓存）
    /// </summary>
    /// <returns>DynamicAPI配置选项</returns>
    public static DynamicApiOptions GetOptions() => _optionsCache.Value;

    /// <summary>
    /// 从配置文件加载选项（带错误处理）
    /// </summary>
    /// <returns>DynamicAPI配置选项</returns>
    private static DynamicApiOptions LoadOptions()
    {
        var jsonFiles = GetJsonFiles();
        
        // 首先查找appsettings.json作为主要配置源
        var primaryConfigFile = jsonFiles.FirstOrDefault(f => f.EndsWith("appsettings.json", StringComparison.OrdinalIgnoreCase));
        if (primaryConfigFile != null)
        {
            var options = TryLoadOptionsFromFile(primaryConfigFile);
            if (options != null)
                return options;
        }

        // 然后尝试其他JSON文件
        foreach (var jsonFile in jsonFiles)
        {
            if (jsonFile == primaryConfigFile) continue;
            
            var options = TryLoadOptionsFromFile(jsonFile);
            if (options != null)
                return options;
        }

        // 如果没有找到配置，返回默认配置
        return new DynamicApiOptions();
    }

    /// <summary>
    /// 尝试从特定文件加载选项（带错误记录）
    /// </summary>
    /// <param name="filePath">配置文件路径</param>
    /// <returns>成功则返回选项，否则返回null</returns>
    private static DynamicApiOptions TryLoadOptionsFromFile(string filePath)
    {
        try
        {
            var configuration = new ConfigurationBuilder()
                .AddJsonFile(filePath, optional: false, reloadOnChange: false) // 修改为false以避免内存泄漏
                .Build();

            var options = configuration.GetSection(OptionSection).Get<DynamicApiOptions>();
            if (options != null)
            {
                Console.WriteLine($"已从{filePath}加载DynamicAPI选项");
                return options;
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"从{filePath}加载配置时出错：{ex.Message}");
        }
        
        return null;
    }

    #region 原始实现 - IsController
    // 不足：逻辑复杂难以理解；硬编码排除特定程序集；没有缓存机制
    // public static bool IsController(Type type)
    // {
    //     // 排除 OData 控制器
    //     if (type.Assembly.GetName().Name.StartsWith("Microsoft.AspNetCore.OData")) return false;
    //
    //     // 不能是非公开、基元类型、值类型、抽象类、接口、泛型类
    //     if (!type.IsPublic || type.IsPrimitive || type.IsValueType || type.IsAbstract || type.IsInterface || type.IsGenericType) return false;
    //
    //     // 控制器 和 IDynamicAPI接口和 RouteAttribute特性 和 DynamicApiAttribute特性
    //     if ((!typeof(Controller).IsAssignableFrom(type) && typeof(ControllerBase).IsAssignableFrom(type))
    //         || typeof(IDynamicAPI).IsAssignableFrom(type)
    //         || (type.IsDefined(typeof(RouteAttribute), true))
    //         || (type.IsDefined(typeof(DynamicApiAttribute), true))
    //         || (type.IsDefined(typeof(ApiSettingAttribute), true))
    //         )
    //     {
    //         return true;
    //     }
    //
    //     return false;
    // }
    #endregion

    // 使用缓存提高类型检查性能
    private static readonly ConcurrentDictionary<Type, bool> _controllerTypeCache = new ConcurrentDictionary<Type, bool>();

    /// <summary>
    /// 判断类型是否为控制器（带缓存）
    /// </summary>
    /// <param name="type">要检查的类型</param>
    /// <returns>如果类型是控制器则为true，否则为false</returns>
    public static bool IsController(Type type)
    {
        return _controllerTypeCache.GetOrAdd(type, t => IsControllerInternal(t));
    }

    /// <summary>
    /// 判断类型是否为控制器的内部实现
    /// </summary>
    /// <param name="type">要检查的类型</param>
    /// <returns>如果类型是控制器则为true，否则为false</returns>
    private static bool IsControllerInternal(Type type)
    {
        // 从配置中获取排除的程序集（如果可用）
        var options = GetOptions();
        var excludedAssemblies = options.ExcludedAssemblies ?? new[] { "Microsoft.AspNetCore.OData" };

        // 检查类型是否来自排除的程序集
        var assemblyName = type.Assembly.GetName().Name;
        if (assemblyName != null && excludedAssemblies.Any(excluded => assemblyName.StartsWith(excluded)))
            return false;

        // 基本类型检查
        if (!type.IsPublic || type.IsPrimitive || type.IsValueType || 
            type.IsAbstract || type.IsInterface || type.IsGenericType)
            return false;

        // 通过继承或特性检查是否为控制器
        bool isAspNetController = typeof(ControllerBase).IsAssignableFrom(type) && 
                                 !typeof(Controller).IsAssignableFrom(type);
        
        bool isDynamicApi = typeof(IDynamicAPI).IsAssignableFrom(type);
        
        bool hasRouteAttribute = type.IsDefined(typeof(RouteAttribute), true);
        bool hasDynamicApiAttribute = type.IsDefined(typeof(DynamicApiAttribute), true);
        bool hasApiSettingAttribute = type.IsDefined(typeof(ApiSettingAttribute), true);

        return isAspNetController || isDynamicApi || hasRouteAttribute || 
               hasDynamicApiAttribute || hasApiSettingAttribute;
    }

    #region 原始实现 - GetActionGroups
    // 不足：性能问题；空异常捕获；硬编码排除系统程序集的逻辑
    // public static IEnumerable<string> GetActionGroups()
    // {
    //     var groupSet = new HashSet<string>();
    //
    //     // 获取所有非系统程序集
    //     var assemblies = AppDomain.CurrentDomain.GetAssemblies()
    //         .Where(ass => !ass.FullName.StartsWith(nameof(System))
    //                    && !ass.FullName.StartsWith(nameof(Microsoft))
    //                    && !ass.FullName.StartsWith("netstandard"))
    //         .Distinct();
    //
    //     foreach (var assembly in assemblies)
    //     {
    //         Type[] types;
    //         try
    //         {
    //             types = assembly.GetTypes();
    //         }
    //         catch
    //         {
    //             continue; // 某些动态程序集可能无法反射，跳过
    //         }
    //
    //         foreach (var type in types.Where(Utils.IsController))
    //         {
    //             MethodInfo[] methods;
    //             try
    //             {
    //                 methods = type.GetMethods();
    //             }
    //             catch
    //             {
    //                 continue;
    //             }
    //
    //             foreach (var method in methods)
    //             {
    //                 var actionAttr = method.GetCustomAttribute<ApiSettingAttribute>(true);
    //                 var controllerAttr = type.GetCustomAttribute<ApiSettingAttribute>(true);
    //                 var setting = actionAttr ?? controllerAttr;
    //
    //                 if (setting?.Groups == null || setting.Groups.Length == 0)
    //                     continue;
    //
    //                 foreach (var group in setting.Groups)
    //                 {
    //                     if (!string.IsNullOrWhiteSpace(group))
    //                         groupSet.Add(group);
    //                 }
    //             }
    //         }
    //     }
    //
    //     groupSet.Add(DefaultGroupName);
    //
    //     return groupSet;
    // }
    #endregion

    /// <summary>
    /// 获取所有Action分组（改进性能和错误处理）
    /// </summary>
    /// <returns>Action分组名称集合</returns>
    public static IEnumerable<string> GetActionGroups()
    {
        var groupSet = new HashSet<string>();
        var options = GetOptions();

        try
        {
            // 从配置获取要扫描的程序集，或使用默认过滤器
            var assembliesToScan = options.IncludedAssemblies?.Length > 0 
                ? AppDomain.CurrentDomain.GetAssemblies()
                    .Where(a => options.IncludedAssemblies.Any(included => 
                        a.FullName?.Contains(included) == true))
                : GetNonSystemAssemblies();

            foreach (var assembly in assembliesToScan)
            {
                ScanAssemblyForGroups(assembly, groupSet);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"扫描程序集获取Action分组时出错：{ex.Message}");
        }

        // 始终包含默认分组
        groupSet.Add(DefaultGroupName);

        return groupSet;
    }

    /// <summary>
    /// 获取非系统程序集
    /// </summary>
    /// <returns>非系统程序集集合</returns>
    private static IEnumerable<Assembly> GetNonSystemAssemblies()
    {
        return AppDomain.CurrentDomain.GetAssemblies()
            .Where(ass => !ass.FullName.StartsWith(nameof(System))
                       && !ass.FullName.StartsWith(nameof(Microsoft))
                       && !ass.FullName.StartsWith("netstandard"))
            .Distinct();
    }

    /// <summary>
    /// 扫描程序集查找Action分组
    /// </summary>
    /// <param name="assembly">要扫描的程序集</param>
    /// <param name="groupSet">要添加分组的集合</param>
    private static void ScanAssemblyForGroups(Assembly assembly, HashSet<string> groupSet)
    {
        Type[] types;
        try
        {
            types = assembly.GetTypes();
        }
        catch (Exception ex)
        {
            Console.WriteLine($"从程序集{assembly.FullName}获取类型时出错：{ex.Message}");
            return;
        }

        foreach (var type in types.Where(IsController))
        {
            ScanTypeForGroups(type, groupSet);
        }
    }

    /// <summary>
    /// 扫描类型查找Action分组
    /// </summary>
    /// <param name="type">要扫描的类型</param>
    /// <param name="groupSet">要添加分组的集合</param>
    private static void ScanTypeForGroups(Type type, HashSet<string> groupSet)
    {
        MethodInfo[] methods;
        try
        {
            methods = type.GetMethods();
        }
        catch (Exception ex)
        {
            Console.WriteLine($"从类型{type.FullName}获取方法时出错：{ex.Message}");
            return;
        }

        // 获取控制器级别的特性（只获取一次，避免重复反射）
        var controllerAttr = type.GetCustomAttribute<ApiSettingAttribute>(true);

        foreach (var method in methods)
        {
            var actionAttr = method.GetCustomAttribute<ApiSettingAttribute>(true);
            var setting = actionAttr ?? controllerAttr;

            if (setting?.Groups == null || setting.Groups.Length == 0)
                continue;

            foreach (var group in setting.Groups)
            {
                if (!string.IsNullOrWhiteSpace(group))
                    groupSet.Add(group);
            }
        }
    }

    #region 原始实现 - 字符串工具
    // 不足：存在两个功能几乎相同的方法，造成代码冗余
    // internal static string ConvertToCamelCase(this string str)
    // {
    //     if (string.IsNullOrEmpty(str) || char.IsLower(str[0]))
    //         return str;
    //     return char.ToLowerInvariant(str[0]) + str.Substring(1);
    // }
    //
    // internal static string ToCamelCase(this string? str)
    // {
    //     if (string.IsNullOrWhiteSpace(str)) return str;
    //
    //     return str.Length == 1
    //         ? str.ToLowerInvariant()
    //         : char.ToLowerInvariant(str[0]) + str.Substring(1);
    // }
    #endregion

    /// <summary>
    /// 将字符串转换为驼峰命名
    /// </summary>
    /// <param name="str">要转换的字符串</param>
    /// <returns>驼峰命名字符串，如果为null/空则返回原字符串</returns>
    internal static string? ToCamelCase(this string? str)
    {
        if (string.IsNullOrWhiteSpace(str)) return str;

        return str.Length == 1
            ? str.ToLowerInvariant()
            : char.ToLowerInvariant(str[0]) + str[1..];
    }

    /// <summary>
    /// 判断类型是否为需要特殊处理的类型
    /// </summary>
    /// <param name="type">要检查的类型</param>
    /// <returns>如果类型需要特殊处理则为true，否则为false</returns>
    internal static bool IsSpecialType(this Type type)
    {
        return typeof(IFormFile).IsAssignableFrom(type) ||
               typeof(IFormFileCollection).IsAssignableFrom(type) ||
               typeof(CancellationToken).IsAssignableFrom(type);
    }

    /// <summary>
    /// 判断参数是否为路由参数
    /// </summary>
    /// <param name="parameter">要检查的参数</param>
    /// <returns>如果参数是路由参数则为true，否则为false</returns>
    internal static bool IsRouteParameter(this ParameterModel parameter)
    {
        return parameter.BindingInfo?.BindingSource?.Id == "Path";
    }

    /// <summary>
    /// Action元数据类
    /// </summary>
    public class ActionMeta
    {
        /// <summary>
        /// 控制器名称
        /// </summary>
        public string? Controller { get; set; }

        /// <summary>
        /// 动作名称
        /// </summary>
        public string? Action { get; set; }

        /// <summary>
        /// 排序
        /// </summary>
        public int Order { get; set; }

        /// <summary>
        /// 分组
        /// </summary>
        public string?[] Groups { get; set; } = Array.Empty<string>();

        /// <summary>
        /// API控制器的显示名称
        /// </summary>
        public string? DisplayName { get; set; }

        /// <summary>
        /// 描述
        /// </summary>
        public string? Description { get; set; }
    }
}